home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
demos
/
OpenGL
/
walker
/
walker.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-11
|
28KB
|
1,106 lines
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <dirent.h>
#include <assert.h>
#include "walker.h"
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define CYCLE_SIZE 100
#define CYCLE_STEP 1.0/CYCLE_SIZE
#define OVERSAMPLE 10
#define MAX_CPOINTS 34 /* 2 end point ones and 10 in the middle */
#define MAX_CSETNAMELEN 25
#define NUM_JOINTS 5
#define CSET_EXT ".cset"
#define CSET_EXTLEN 5
#include "walkviewer.h"
typedef enum { CMENU_QUIT, CMENU_CURVE, CMENU_HORIZ, CMENU_RESET,
CMENU_WALK, CMENU_DONEEDIT, CMENU_SAVE, CMENU_LOAD,
CMENU_MIRROR
} CurveMenuChoices;
typedef enum { WIRECUBE, SOLIDCUBE, CYLINDER1, CYLINDER2 } ModelTypes;
int GuyModel = SOLIDCUBE;
/***************************************************************/
/*************************** GLOBALS ***************************/
/***************************************************************/
GLuint HorizontalList, AxesList, /* Display lists */
CurveLists, ControlPtsLists; /* Firsts of groups of display lists */
int CurveAsPoints = 0, /* Display curve as points? */
DrawHorizontals = 0, /* Draw horizontal lines? */
EditingCurve = -1; /* Editing what curve, -1 means none */
int CurveWindow, /* Glut window id's to two top level windows */
GuyWindow;
int MirrorLegs = 0;
int CurveMenu = -1,
CurveEditMenu = -1,
StepSizeMenu = -1,
LoadMenu = -1,
SaveMenu = -1;
char *CSetNames[MAX_CSETNAMELEN];
int CurrentCurve = -1; /* Curve loaded, index to CSetNames */
GLfloat Walk_cycle[2][NUM_JOINTS][CYCLE_SIZE]; /* array of computed angles */
int Step = CYCLE_SIZE/2; /* Position in cycle, start in middle */
float fStep = CYCLE_SIZE/2; /* floating point for non-integer steping */
float IncStep = 1.0;
typedef struct ControlPts {
int numpoints;
float xcoords[MAX_CPOINTS];
float angles[MAX_CPOINTS];
} tControlPts;
tControlPts RotCurve[NUM_JOINTS]; /* series of cntrl points for ea joint */
int Walking = 0, /* Guy is walking? */
ViewPerspective = 1, /* Perspective or orthographic views */
DrawAxes = 0; /* Draw axes for alignment */
int CurveWWidth, /* Dimensions of curve window */
CurveWHeight;
int CurveDownBtn = -1, /* mouse stuff, for editing curves */
WasWalking,
CurvePickedPoint = -1,
CurveLastX,
CurveLastY;
int CurveWindowVisible = 1;
/* prototypes */
void RedisplayBoth(void);
void IncrementStep(void);
void CurveCPointDrag(void);
void CurveHandleMenu(int value);
void StopWalking(void);
void CurveHandleEditMenu(int curve);
void ComputeCSetAndMakeLists(void);
int MakeLoadAndSaveMenus(void);
void CurveMenuInit(void);
void SetWindowTitles(char *csetname);
/***************************************************************/
/**************************** BEZIER ***************************/
/***************************************************************/
/* Matrix times a vector dest = m*v */
void MultMV(float m[3][4], float v[4], float dest[3])
{
int i, j;
for (i = 0; i < 3; i++) {
dest[i] = 0;
for (j = 0; j < 4; j++)
dest[i] += m[i][j] * v[j];
}
}
/* Matrix multiplication, dest = m1*m2 */
void MultM(float m1[3][4], float m2[4][4], float dest[3][4])
{
int i, j, k;
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++) {
dest[i][j] = 0;
for (k = 0; k < 4; k++)
dest[i][j] += (m1[i][k] * m2[k][j]);
}
}
void ComputeCurve(int joint)
{
float prod[3][4], tm[4], pos[3];
float t = 0, tinc = (float)CYCLE_STEP/OVERSAMPLE;
int ctlpoint, i;
float BBasis[4][4] = {{-1, 3, -3, 1}, {3, -6, 3, 0},
{-3, 3, 0, 0}, {1, 0, 0, 0}};
int lastindex, newindex;
float pointset[3][4];
for (i = 0; i < 4; i++) /* z's are always zero, only 2-d */
pointset[2][i] = 0;
lastindex = -1;
for(ctlpoint = 0; ctlpoint < RotCurve[joint].numpoints; ctlpoint += 3) {
t = 0;
for (i = 0; i < 4; i++)
pointset[0][i] = RotCurve[joint].xcoords[ctlpoint + i];
for (i = 0; i < 4; i++)
pointset[1][i] = RotCurve[joint].angles[ctlpoint + i];
MultM(pointset, BBasis, prod);
while (t <= 1) {
tm[0] = t*t*t;
tm[1] = t*t;
tm[2] = t;
tm[3] = 1;
MultMV(prod, tm, pos);
newindex = (int)(pos[0]*(CYCLE_SIZE-1));
if ((int)(newindex > lastindex)) { /* go at least one */
Walk_cycle[0][joint][newindex] = pos[1];
lastindex++;
}
t += tinc;
}
}
for (i = 0; i < CYCLE_SIZE; i++) { /* copy to other leg, out-o-phase */
if (MirrorLegs)
Walk_cycle[1][joint][i] =
Walk_cycle[0][joint][i];
else
Walk_cycle[1][joint][i] =
Walk_cycle[0][joint][(i+(CYCLE_SIZE/2))%CYCLE_SIZE];
}
}
/***************************************************************/
/************************* CURVE I/O ***************************/
/***************************************************************/
void FlatCSet(void)
{
int joint;
for (joint = 0; joint < NUM_JOINTS; joint++) {
RotCurve[joint].numpoints = 4;
RotCurve[joint].xcoords[0] = 0.0;
RotCurve[joint].angles[0] = 0.0;
RotCurve[joint].xcoords[1] = 0.2;
RotCurve[joint].angles[1] = 0.0;
RotCurve[joint].xcoords[2] = 0.8;
RotCurve[joint].angles[2] = 0.0;
RotCurve[joint].xcoords[3] = 1.0;
RotCurve[joint].angles[3] = 0.0;
}
}
int ReadCSetFromFile(char *filename)
{
FILE *infile = fopen(filename, "r");
int numjoints, numpoints, joint, point, mirrorlegs;
float value;
if (infile == NULL)
goto abort;
if (!fscanf(infile, " %d", &numjoints) || numjoints != NUM_JOINTS)
goto abort;
if (!fscanf(infile, " %d", &mirrorlegs) || (mirrorlegs != 0 &&
mirrorlegs != 1))
goto abort;
MirrorLegs = mirrorlegs;
for (joint = 0; joint < NUM_JOINTS; joint++) {
if (!fscanf(infile, " %d", &numpoints) || numpoints < 4 ||
numpoints > MAX_CPOINTS)
goto abort;
RotCurve[joint].numpoints = numpoints;
for (point = 0; point < numpoints; point++) {
if (!fscanf(infile, " %f", &value))
goto abort;
RotCurve[joint].xcoords[point] = value;
}
for (point = 0; point < numpoints; point++) {
if (!fscanf(infile, " %f", &value))
goto abort;
RotCurve[joint].angles[point] = value;
}
}
fclose(infile);
return 0;
abort:
fclose(infile);
fprintf(stderr, "Something went wrong while reading file %s\n", filename);
FlatCSet();
return -1;
}
void WriteCSetToFile(char *filename)
{
FILE *outfile = fopen(filename, "w+");
int joint, point;
if (outfile == NULL) {
fprintf(stderr, "Error: could not create file %s\n", filename);
return;
}
fprintf(outfile, "%d\n", NUM_JOINTS);
fprintf(outfile, "%d\n", MirrorLegs);
for (joint = 0; joint < NUM_JOINTS; joint++) {
fprintf(outfile, "%d\n", RotCurve[joint].numpoints);
for (point = 0; point < RotCurve[joint].numpoints; point++) {
fprintf(outfile, "%f ", RotCurve[joint].xcoords[point]);
}
fprintf(outfile, "\n");
for (point = 0; point < RotCurve[joint].numpoints; point++) {
fprintf(outfile, "%f ", RotCurve[joint].angles[point]);
}
fprintf(outfile, "\n");
}
fclose(outfile);
}
void HandleLoadMenu(int cset)
{
char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
if (cset == -1) {
MakeLoadAndSaveMenus();
CurveMenuInit();
} else {
(void)strcpy(filename, CSetNames[cset]);
(void)strcat(filename, CSET_EXT);
if (ReadCSetFromFile(filename) == 0) {
glutSetMenu(SaveMenu);
glutChangeToMenuEntry(1, CSetNames[cset], cset);
ComputeCSetAndMakeLists();
SetWindowTitles(CSetNames[cset]);
RedisplayBoth();
}
}
}
void HandleSaveMenu(int cset)
{
char filename[MAX_CSETNAMELEN + CSET_EXTLEN + 1];
(void)strcpy(filename, CSetNames[cset]);
(void)strcat(filename, CSET_EXT);
WriteCSetToFile(filename);
ComputeCSetAndMakeLists();
RedisplayBoth();
}
int MakeLoadAndSaveMenus(void)
{
DIR *dirp = opendir(".");
struct dirent *direntp;
int csetnum = 0;
char *newcsetname;
if (LoadMenu != -1)
glutDestroyMenu(LoadMenu);
if (SaveMenu != -1)
glutDestroyMenu(SaveMenu);
SaveMenu = glutCreateMenu(HandleSaveMenu);
LoadMenu = glutCreateMenu(HandleLoadMenu);
if (dirp == NULL) {
fprintf(stderr, "Error opening current dir in MakeLoadAndSaveMenus\n");
return(0);
}
while ((direntp = readdir(dirp)) != NULL) {
char *ext = direntp->d_name + (strlen(direntp->d_name) - CSET_EXTLEN);
if (!strcmp(ext, CSET_EXT)) {
newcsetname = malloc(strlen(direntp->d_name) - CSET_EXTLEN + 1);
strncpy(newcsetname, direntp->d_name,
strlen(direntp->d_name) - CSET_EXTLEN);
newcsetname[strlen(direntp->d_name) - CSET_EXTLEN] = 0;
CSetNames[csetnum] = newcsetname;
glutAddMenuEntry(newcsetname, csetnum++);
}
}
closedir(dirp);
glutSetMenu(LoadMenu);
glutAddMenuEntry("-> Rescan Directory <-", -1);
glutSetMenu(SaveMenu);
CSetNames[csetnum] = "NewCurve0";
glutAddMenuEntry("NewCurve0", csetnum++);
CSetNames[csetnum] = "NewCurve1";
glutAddMenuEntry("NewCurve1", csetnum++);
CSetNames[csetnum] = "NewCurve2";
glutAddMenuEntry("NewCurve2", csetnum++);
return (csetnum - 2); /* just indicate curves in Load menu */
}
/***************************************************************/
/********************* DISPLAY LISTS ***************************/
/***************************************************************/
void MakeCurveList(int joint)
{
int i;
glNewList(CurveLists+joint, GL_COMPILE);
glColor3f(1, 1, 1);
for (i = 0; i < CYCLE_SIZE; i++) {
glVertex3f((GLfloat)i/CYCLE_SIZE, Walk_cycle[0][joint][i]/180, 0);
}
glEndList();
}
void MakeCPointList(int joint)
{
int point;
glNewList(ControlPtsLists+joint, GL_COMPILE);
glColor3f(0, 0.4, 0);
glBegin(GL_LINE_STRIP);
for (point = 0; point < RotCurve[joint].numpoints; point++) {
if (!((point-2) % 3)) {
glEnd();
glBegin(GL_LINE_STRIP);
}
glVertex3f(RotCurve[joint].xcoords[point],
(RotCurve[joint].angles[point])/180.0, 0.0);
}
glEnd();
glBegin(GL_POINTS);
for (point = 0; point < RotCurve[joint].numpoints; point++) {
if (point % 3)
glColor3f(0, 0.7, 0);
else
glColor3f(0.7, 0.0, 0);
glVertex3f(RotCurve[joint].xcoords[point],
(RotCurve[joint].angles[point])/180, 0);
}
glEnd();
glEndList();
}
void MakeJointLists(int joint)
{
MakeCurveList(joint);
MakeCPointList(joint);
}
void ComputeCSetAndMakeLists(void)
{
int joint;
for(joint = 0; joint < NUM_JOINTS; joint++) {
ComputeCurve(joint);
MakeJointLists(joint);
}
}
void MakeLists(void)
{
HorizontalList = glGenLists(1);
glNewList(HorizontalList, GL_COMPILE);
{
float line1 = 25.0/180,
line2 = 35.0/180,
line3 = 45.0/180;
glColor3f(0, 0, 0.7);
glPushAttrib(GL_ENABLE_BIT);
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINES);
glVertex3f(0, 0, 0.5);
glVertex3f(1, 0, 0.5);
glVertex3f(0, line1, 0.5); glVertex3f(1, line1, 0.5);
glVertex3f(0, -line1, 0.5); glVertex3f(1, -line1, 0.5);
glVertex3f(0, line2, 0.5); glVertex3f(1, line2, 0.5);
glVertex3f(0, -line2, 0.5); glVertex3f(1, -line2, 0.5);
glVertex3f(0, line3, 0.5); glVertex3f(1, line3, 0.5);
glVertex3f(0, -line3, 0.5); glVertex3f(1, -line3, 0.5);
glEnd();
glPopAttrib();
}
glEndList();
CurveLists = glGenLists(NUM_JOINTS);
assert(CurveLists != 0);
ControlPtsLists = glGenLists(NUM_JOINTS);
assert(ControlPtsLists != 0);
ComputeCSetAndMakeLists();
}
/***************************************************************/
/********************* curve WINDOW ****************************/
/***************************************************************/
void CurveReshape(int w, int h)
{
glViewport(0,0,w,h);
CurveWWidth = w;
CurveWHeight = h;
glFlush();
}
void CurveDisplay(void)
{
int joint, otherlegstep;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0, 0.5, 0);
for (joint = NUM_JOINTS-1; joint >= 0; joint--) {
if (DrawHorizontals)
glCallList(HorizontalList);
(CurveAsPoints) ?
glBegin(GL_POINTS) :
glBegin(GL_LINE_STRIP);
glCallList(CurveLists+joint);
glEnd();
if (joint == EditingCurve) {
glPointSize(5.0);
glCallList(ControlPtsLists+EditingCurve);
glPointSize(1.0);
}
glTranslatef(0, 1, 0);
}
glPopMatrix();
otherlegstep = (Step+50) % CYCLE_SIZE;
/* draw vertical line */
glColor3f(1, 1, 1);
glBegin(GL_LINES);
glVertex3f((GLfloat)Step/CYCLE_SIZE, 0, 0);
glVertex3f((GLfloat)Step/CYCLE_SIZE, NUM_JOINTS, 0);
if (!MirrorLegs) {
glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, 0, 0);
glVertex3f((GLfloat)otherlegstep/CYCLE_SIZE, NUM_JOINTS, 0);
}
glEnd();
glFlush();
glutSwapBuffers();
}
void CurveGLInit(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,1,0,NUM_JOINTS,1,-1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLineStipple(1, 0x00FF);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glFlush();
}
void CurveHandleButton(int button, int state, int x, int y)
{
if (button == GLUT_RIGHT_BUTTON )
return;
if (state == GLUT_DOWN && CurveDownBtn == -1) {
if (button == GLUT_MIDDLE_BUTTON)
CurveHandleMenu(CMENU_WALK);
else
fStep = Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE);
CurveDownBtn = button;
WasWalking = Walking;
StopWalking();
RedisplayBoth();
} else if (button == CurveDownBtn) {
CurveDownBtn = -1;
if (WasWalking) {
Walking = 1;
agvSetAllowIdle(0);
glutIdleFunc(IncrementStep);
}
}
}
float CurveEditConstrain(float fx)
{
if (CurvePickedPoint == 0)
fx = 0;
else if (CurvePickedPoint == RotCurve[EditingCurve].numpoints-1)
fx = 1;
else if (!(CurvePickedPoint % 3)) { /* is a pivot */
fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);
fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-3]);
fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+3]);
} else if (!((CurvePickedPoint - 1) % 3)) { /* is right slope */
fx = MAX(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint-1]);
} else {
fx = MIN(fx, RotCurve[EditingCurve].xcoords[CurvePickedPoint+1]);
}
return fx;
}
void RemovePoint(int pt)
{
int i;
for (i = pt - 1; i < RotCurve[EditingCurve].numpoints; i++) {
RotCurve[EditingCurve].xcoords[i] = RotCurve[EditingCurve].xcoords[i+3];
RotCurve[EditingCurve].angles[i] = RotCurve[EditingCurve].angles[i+3];
}
RotCurve[EditingCurve].numpoints -= 3;
}
void AddPoint(float fx)
{
int i, j;
if (fx < 0.05 || fx > 0.95 || RotCurve[EditingCurve].numpoints + 3 >=
MAX_CPOINTS)
return;
for (i = 3; i < RotCurve[EditingCurve].numpoints; i += 3) {
if (fx < RotCurve[EditingCurve].xcoords[i]) {
for (j = RotCurve[EditingCurve].numpoints + 2; j > i + 1; j--) {
RotCurve[EditingCurve].xcoords[j] =
RotCurve[EditingCurve].xcoords[j-3];
RotCurve[EditingCurve].angles[j] =
RotCurve[EditingCurve].angles[j-3];
}
RotCurve[EditingCurve].xcoords[i] = fx;
RotCurve[EditingCurve].angles[i] =
Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)];
RotCurve[EditingCurve].xcoords[i-1] = fx - 0.05;
RotCurve[EditingCurve].angles[i-1] =
Walk_cycle[0][EditingCurve][(int)((fx-0.05)*CYCLE_SIZE)];
RotCurve[EditingCurve].xcoords[i+1] = fx + 0.05;
RotCurve[EditingCurve].angles[i+1] =
Walk_cycle[0][EditingCurve][(int)((fx+0.05)*CYCLE_SIZE)];
RotCurve[EditingCurve].numpoints += 3;
break;
}
}
}
void CurveEditHandleButton(int button, int state, int x, int y)
{
float fx, fy;
int point;
fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
fx = (float)x/CurveWWidth;
if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON &&
CurveDownBtn == -1) {
CurvePickedPoint = -1;
for (point = 0; point < RotCurve[EditingCurve].numpoints; point++) {
if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
CurvePickedPoint = point;
CurveLastX = x;
CurveLastY = y;
glutIdleFunc(CurveCPointDrag);
break;
}
}
if (CurvePickedPoint == -1)
CurveHandleButton(button, state, x, y);
CurveDownBtn = button;
} else if (state == GLUT_DOWN && button == GLUT_MIDDLE_BUTTON &&
CurveDownBtn == -1) {
for (point = 3; point < RotCurve[EditingCurve].numpoints - 1; point += 3) {
if (fabs(RotCurve[EditingCurve].xcoords[point] - fx) < 0.01 &&
fabs(RotCurve[EditingCurve].angles[point] - fy) < 4) {
break;
}
}
if (point >= 3 && point < RotCurve[EditingCurve].numpoints - 1)
RemovePoint(point);
else if (fabs(Walk_cycle[0][EditingCurve][(int)(fx*CYCLE_SIZE)] - fy) < 4)
AddPoint(fx);
ComputeCurve(EditingCurve);
MakeJointLists(EditingCurve);
RedisplayBoth();
} else if (button == GLUT_LEFT_BUTTON && button == CurveDownBtn) {
y = MAX(y, 0); y = MIN(y, CurveWHeight);
x = MAX(x, 0); x = MIN(x, CurveWWidth);
fy = -(((float)y - ((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
fx = (float)x/CurveWWidth;
CurveDownBtn = -1;
if (CurvePickedPoint != -1) {
fx = CurveEditConstrain(fx);
RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;
ComputeCurve(EditingCurve);
MakeJointLists(EditingCurve);
glutIdleFunc(NULL);
RedisplayBoth();
}
}
}
void CurveHandleMotion(int x, int y)
{
if (CurvePickedPoint == -1) {
if (CurveDownBtn == GLUT_LEFT_BUTTON || CurveDownBtn ==
GLUT_MIDDLE_BUTTON) {
Step = (int)((float)x/glutGet(GLUT_WINDOW_WIDTH) * CYCLE_SIZE)
% CYCLE_SIZE;
if (Step < 0)
Step = CYCLE_SIZE + Step;
fStep = Step;
RedisplayBoth();
}
} else {
y = MAX(y, 0); y = MIN(y, CurveWHeight);
x = MAX(x, 0); x = MIN(x, CurveWWidth);
CurveLastX = x;
CurveLastY = y;
}
}
void CurveCPointDrag(void)
{
float fx, fy;
if (CurveDownBtn == GLUT_LEFT_BUTTON && CurvePickedPoint != -1) {
fy = -(((float)CurveLastY -
((float)CurveWHeight/NUM_JOINTS * EditingCurve)) /
((float)CurveWHeight/NUM_JOINTS) - 0.5) * 180.0,
fx = (float)CurveLastX/CurveWWidth;
fx = CurveEditConstrain(fx);
RotCurve[EditingCurve].xcoords[CurvePickedPoint] = fx;
RotCurve[EditingCurve].angles[CurvePickedPoint] = fy;
ComputeCurve(EditingCurve);
MakeJointLists(EditingCurve);
RedisplayBoth();
}
}
void CurveHandleKeys(unsigned char key, int x, int y)
{
if (key > '0' && key < '9')
CurveHandleEditMenu((key-'0')-1);
else if (key == 'd')
CurveHandleMenu(CMENU_DONEEDIT);
else {
switch(key) {
case 'f':
case ' ': Step++;
StopWalking(); break;
case 'F': Step += 5;
StopWalking(); break;
case 'b': Step--;
StopWalking(); break;
case 'B': Step -= 5;
StopWalking(); break;
}
Step %= CYCLE_SIZE;
if (Step < 0)
Step = CYCLE_SIZE + Step;
fStep = Step;
RedisplayBoth();
}
}
void CurveHandleEditMenu(int curve)
{
if (curve >= NUM_JOINTS)
return;
if (EditingCurve == -1) {
WasWalking = Walking;
Walking = 0;
agvSetAllowIdle(0); /* don't allow spinning, just slows us down */
glutIdleFunc(NULL);
glutMouseFunc(CurveEditHandleButton);
}
EditingCurve = curve;
glutPostRedisplay();
}
void CurveHandleSZMenu(int size)
{
IncStep = (float)size/100;
}
void CurveHandleMenu(int value)
{
switch (value) {
case CMENU_QUIT:
exit(0);
break;
case CMENU_CURVE:
CurveAsPoints = !CurveAsPoints;
glutPostRedisplay();
break;
case CMENU_HORIZ:
DrawHorizontals = !DrawHorizontals;
glutPostRedisplay();
break;
case CMENU_WALK:
if (EditingCurve != -1)
break;
Walking = !Walking;
if (Walking) {
agvSetAllowIdle(0);
glutIdleFunc(IncrementStep);
} else {
agvSetAllowIdle(1);
}
break;
case CMENU_DONEEDIT:
glutMouseFunc(CurveHandleButton);
EditingCurve = -1;
CurvePickedPoint = -1;
Walking = WasWalking;
if (Walking)
glutIdleFunc(IncrementStep);
else
agvSetAllowIdle(1);
glutPostRedisplay();
break;
case CMENU_RESET:
FlatCSet();
ComputeCSetAndMakeLists();
glutPostRedisplay();
break;
case CMENU_MIRROR:
MirrorLegs = !MirrorLegs;
ComputeCSetAndMakeLists();
glutPostRedisplay();
}
}
void CurveMenuInit(void)
{
int i;
char label[3];
if (CurveEditMenu != -1) {
glutDestroyMenu(CurveEditMenu);
glutDestroyMenu(CurveMenu);
glutDestroyMenu(StepSizeMenu);
}
CurveEditMenu = glutCreateMenu(CurveHandleEditMenu);
for (i = 0; i < NUM_JOINTS; i++) {
sprintf(label, " %d ", i+1);
glutAddMenuEntry(label, i);
}
StepSizeMenu = glutCreateMenu(CurveHandleSZMenu);
glutAddMenuEntry("0.25", 25);
glutAddMenuEntry("0.5", 50);
glutAddMenuEntry("1.0", 100);
glutAddMenuEntry("2.0", 200);
glutAddMenuEntry("3.0", 300);
glutAddMenuEntry("5.0", 500);
CurveMenu = glutCreateMenu(CurveHandleMenu);
glutAddSubMenu("Load Curve Set", LoadMenu);
glutAddSubMenu("Save As Curve Set", SaveMenu);
glutAddSubMenu("Edit Curve", CurveEditMenu);
glutAddMenuEntry("Done Editing", CMENU_DONEEDIT);
glutAddMenuEntry("Flatten Curve Set", CMENU_RESET);
glutAddMenuEntry("Toggle mirrored", CMENU_MIRROR);
glutAddSubMenu("Step size", StepSizeMenu);
glutAddMenuEntry("Toggle dotted", CMENU_CURVE);
glutAddMenuEntry("Toggle horizontals", CMENU_HORIZ);
glutAddMenuEntry("Toggle walking", CMENU_WALK);
glutAddMenuEntry("Quit", CMENU_QUIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void CurveVisible(int v)
{
if (v == GLUT_VISIBLE)
CurveWindowVisible = 1;
else
CurveWindowVisible = 0;
}
/***************************************************************/
/*********************** GUY WINDOW ****************************/
/***************************************************************/
void GuyDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFlush();
glLoadIdentity();
agvViewTransform();
if (DrawAxes)
glCallList(AxesList);
switch(GuyModel) {
case WIRECUBE: DrawTheGuy_WC(); break;
case SOLIDCUBE: DrawTheGuy_SC(); break;
case CYLINDER1: DrawTheGuy_SL(); break;
case CYLINDER2: DrawTheGuy_SL2(); break;
}
glutSwapBuffers();
glFlush();
}
void GuyReshape(int w, int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (ViewPerspective)
gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
else
glOrtho(-1.2, 1.2, -1.2, 1.2, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glFlush();
}
void GuyGLInit(void)
{
GLfloat mat_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 0.3, 0.5, 0.8, 0.0 };
GLfloat lm_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lm_ambient);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glShadeModel(GL_SMOOTH);
/* Cylinder stuff */
StoreTheGuy_SL();
StoreTheGuy_SL2();
}
void GuyHandleKeys(unsigned char key, int x, int y)
{
switch(key) {
case 'f':
case ' ': Step++;
StopWalking(); break;
case 'F': Step += 5;
StopWalking(); break;
case 'b': Step--;
StopWalking(); break;
case 'B': Step -= 5;
StopWalking(); break;
}
Step %= CYCLE_SIZE;
if (Step < 0)
Step = CYCLE_SIZE + Step;
agvHandleKeys(key, x, y);
RedisplayBoth();
}
typedef enum { GMENU_QUIT, GMENU_CURVE, GMENU_HORIZ,
GMENU_AXES, GMENU_PERSP } GuyMenuChoices;
void GuyModelHandleMenu(int model)
{
GuyModel = model;
if (model == WIRECUBE)
glDisable(GL_LIGHTING);
else
glEnable(GL_LIGHTING);
glutPostRedisplay();
}
void GuyHandleMenu(int value)
{
switch (value) {
case GMENU_QUIT:
exit(0);
break;
case GMENU_AXES:
DrawAxes = !DrawAxes;
glutPostRedisplay();
break;
case GMENU_PERSP:
ViewPerspective = !ViewPerspective;
GuyReshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
glutPostRedisplay();
break;
}
}
void GuyMenuInit(void)
{
int sub2, sub1 = glutCreateMenu(agvSwitchMoveMode);
glutAddMenuEntry("Flying move", FLYING);
glutAddMenuEntry("Polar move", POLAR);
sub2 = glutCreateMenu(GuyModelHandleMenu);
glutAddMenuEntry("Wire cubes", WIRECUBE);
glutAddMenuEntry("Solid cubes", SOLIDCUBE);
glutAddMenuEntry("Cylinder 1", CYLINDER1);
glutAddMenuEntry("Cylinder 2", CYLINDER2);
glutCreateMenu(GuyHandleMenu);
glutAddSubMenu("Viewing", sub1);
glutAddSubMenu("Model", sub2);
glutAddMenuEntry("Toggle Axes", GMENU_AXES);
glutAddMenuEntry("Toggle Perspective View", GMENU_PERSP);
glutAddMenuEntry("Quit", GMENU_QUIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
/***************************************************************/
/********************* BOTH WINDOWS ****************************/
/***************************************************************/
void RedisplayBoth(void)
{
glutSetWindow(GuyWindow);
glutPostRedisplay();
if (CurveWindowVisible) {
glutSetWindow(CurveWindow);
glutPostRedisplay();
}
}
void IncrementStep(void)
{
fStep = fmod(fStep + IncStep, CYCLE_SIZE);
Step = (int)fStep;
if (agvMoving)
agvMove();
RedisplayBoth();
}
void StopWalking(void)
{
if (Walking) {
Walking = 0;
agvSetAllowIdle(1);
}
}
void SetWindowTitles(char *csetname)
{
char windowtitle[MAX_CSETNAMELEN + 20];
strcpy(windowtitle, "Rotation Curves: ");
strcat(windowtitle, csetname);
glutSetWindow(CurveWindow);
glutSetWindowTitle(windowtitle);
strcpy(windowtitle, "The Guy: ");
strcat(windowtitle, csetname);
glutSetWindow(GuyWindow);
glutSetWindowTitle(windowtitle);
}
/***************************************************************/
/***************************** MAIN ****************************/
/***************************************************************/
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitWindowPosition(700, 250);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
GuyWindow = glutCreateWindow("The Guy:");
agvInit(!Walking);
AxesList = glGenLists(1);
agvMakeAxesList(AxesList);
GuyGLInit();
GuyMenuInit();
glutDisplayFunc(GuyDisplay);
glutReshapeFunc(GuyReshape);
glutKeyboardFunc(GuyHandleKeys);
glutInitWindowSize(512, 1024);
glutInitWindowPosition(100, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
CurveWindow = glutCreateWindow("Rotation Curves:");
CurveGLInit();
glutDisplayFunc(CurveDisplay);
glutReshapeFunc(CurveReshape);
glutMouseFunc(CurveHandleButton);
glutMotionFunc(CurveHandleMotion);
glutKeyboardFunc(CurveHandleKeys);
glutVisibilityFunc(CurveVisible);
FlatCSet();
MakeLists();
if (MakeLoadAndSaveMenus() > 0) /* read first curve if there was one */
HandleLoadMenu(0);
CurveMenuInit();
glutMainLoop();
}